package com.school.fuyuan.common.aspect;

import com.school.fuyuan.business.constants.InfoConstants;
import com.school.fuyuan.business.mapper.PrivilegeMapper;
import com.school.fuyuan.business.mapper.RoleMapper;
import com.school.fuyuan.business.mapper.UserMapper;
import com.school.fuyuan.business.model.po.Privilege;
import com.school.fuyuan.business.model.po.User;
import com.school.fuyuan.common.annotation.Authenticate;
import com.school.fuyuan.common.exception.CommonRuntimeException;
import com.school.fuyuan.common.message.RequestHead;
import com.school.fuyuan.common.message.RequestMsg;
import com.school.fuyuan.common.util.ParameterUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zrhong
 * @version 1.0
 * @date 2019/3/3 20:40
 * @description
 */
@Aspect
@Order(2)
@Component
public class AuthcAspect {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final PrivilegeMapper privilegeMapper;
    private final RoleMapper roleMapper;

    public AuthcAspect(PrivilegeMapper privilegeMapper, RoleMapper roleMapper) {
        this.privilegeMapper = privilegeMapper;
        this.roleMapper = roleMapper;
    }

    @Before(value = "@annotation(authc)")
    public void doBefore(JoinPoint joinPoint, Authenticate authc) {

        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return;
        }

        RequestMsg requestMsg = null;

        for (Object obj : args) {
            if (obj instanceof RequestMsg) {
                requestMsg = (RequestMsg) obj;
                break;
            }
        }

        if (requestMsg == null) {
            return;
        }

        //未开启aop自动校验则直接返回
        if (!authc.openAuth()) {
            return;
        }

        String[] specifiedAuthItems = authc.authItems();

        if (ParameterUtils.isEmpty(specifiedAuthItems)) {
            return;
        }

        Object data = requestMsg.getData();
        if (data == null) {
            return;
        }
        List<String> authItems = Arrays.asList(specifiedAuthItems);
        RequestHead head = requestMsg.getHead();
        String userId = head.getUserId();
        List<Integer> roleIds = roleMapper.getUserRole(userId);
        if (ParameterUtils.isEmpty(roleIds)) {
            throw new CommonRuntimeException("403", "权限不足，请联系管理员");
        }
        List<Integer> privilegeIds = roleMapper.getPrivileges(roleIds);
        if (ParameterUtils.isEmpty(privilegeIds)) {
            throw new CommonRuntimeException("403", "权限不足，请联系管理员");
        }
        List<Privilege> privileges = privilegeMapper.getPrivileges(privilegeIds);
        List<String> privilegePaths = privileges.stream().map(Privilege::getPrivilegePath).collect(Collectors.toList());
        authItems.retainAll(privilegePaths);
        if (authItems.size() <= 0) {
            throw new CommonRuntimeException("403", "权限不足，请联系管理员");
        }
    }
}
